package com.jiang.mybatis_plus.config.swagger;

import com.fasterxml.classmate.ResolvedType;
import com.jiang.core.annto.SwaggerDisplayEnum;
import io.swagger.annotations.ApiModelProperty;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.stereotype.Component;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spi.schema.ModelPropertyBuilderPlugin;
import springfox.documentation.spi.schema.contexts.ModelPropertyContext;

import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;

import static springfox.documentation.schema.Annotations.findPropertyAnnotation;
import static springfox.documentation.swagger.schema.ApiModelProperties.findApiModePropertyAnnotation;

/**
 * <p>
 * SwaggerConfig2:
 * </p>
 *
 * @author jiang
 * @since 2022/10/26
 */
@Slf4j
@Component
public class SwaggerEnumModelPropertyBuilderPlugin implements ModelPropertyBuilderPlugin {
    @Override
    public void apply(ModelPropertyContext context) {
        //为枚举字段设置注释
        Optional<ApiModelProperty> annotation = Optional.empty();
        if (context.getAnnotatedElement().isPresent()) {
            annotation = annotation.map(java.util.Optional::of).orElse(findApiModePropertyAnnotation(context.getAnnotatedElement().get()));
        }
        if (context.getBeanPropertyDefinition().isPresent()) {
            annotation = annotation.map(Optional::of).orElse(findPropertyAnnotation(context.getBeanPropertyDefinition().get(),ApiModelProperty.class));
        }

        Class rawPrimaryType;
        try {
            String enumPackage = annotation.get().notes();
            rawPrimaryType = Class.forName(enumPackage);
        } catch (ClassNotFoundException e) {
            return;
        }

        Object[] subItemRecords = null;
        SwaggerDisplayEnum swaggerDisplayEnum = AnnotationUtils.findAnnotation(rawPrimaryType, SwaggerDisplayEnum.class);
        if (null != swaggerDisplayEnum && Enum.class.isAssignableFrom(rawPrimaryType)) {
            subItemRecords = rawPrimaryType.getEnumConstants();
        }
        if (null == subItemRecords) {
            return;
        }

        final List<String> displayValues = Arrays.stream(subItemRecords).filter(Objects::nonNull)
                .map(Object::toString).filter(Objects::nonNull).collect(Collectors.toList());

        String joinText = " [" + String.join(", ", displayValues) + "]";
        try {
            joinText = "<p>["+ annotation.get().notes()+"]<p>" + annotation.get().value() +":"+ joinText +"<p>";
        } catch (Exception e) {
            log.error(e.getMessage());
        }

        final Class fieldType = context.getBeanPropertyDefinition().get().getField().getRawType();
        final ResolvedType resolvedType = context.getResolver().resolve(fieldType);
        context.getBuilder().description(joinText).type(resolvedType);
    }

    @Override
    public boolean supports(DocumentationType documentationType) {
        return true;
    }
}